package com.charging.business.service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.charging.business.config.MinFeeManager;
import com.charging.business.domain.FeeEntryInfoModel;
import com.charging.business.enums.Issuer;
import com.charging.business.enums.SpecialSituation;
import com.charging.business.enums.Vtype;
import com.charging.business.exception.CustomizeException;
import com.charging.business.gantry.EntryFeeCalcResponse;
import com.charging.business.gantry.GantryCalcUtils;
import com.charging.business.jin.JinOnLineRequest;
import com.charging.business.qin.Db3FileUtils;
import com.charging.business.qin.QinOnLineRequest;
import com.charging.business.utils.BasicUtil;
import com.charging.business.utils.DateEx;
import com.charging.business.utils.RosterUtils;
import com.charging.business.utils.PayUtil;
import com.charging.business.vo.CustomOnlineResponse;
import com.charging.business.vo.FeeExCalcRequest;
import com.charging.business.vo.FeeExCalcResponse;
import com.charging.business.vo.obj.CpcFeeInfo;
import com.charging.business.vo.obj.MiniFeeInfo;
import com.charging.business.vo.obj.OnlineFeeInfo;
import com.charging.business.vo.obj.SplitProvinceMini;
import com.charging.common.utils.DateUtils;
import com.charging.common.utils.StringUtils;
import com.charging.common.utils.uuid.IdUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.Objects;

/**
 * @author JerryLu
 * @date 2024/9/27 11:15
 * @description 出口CPC刷卡计费
 */
@Component
public class FeeExCpcHandle {
    private static final Logger logger = LoggerFactory.getLogger(FeeExCpcHandle.class);
    //上次过门架时间
    private static long lastGantryTime = 0L;
    private static Date enTime;
    //出口时间
    private static Date exTime;
    //兜底收费标识
    private static boolean beWantMinFee = false;
    //在线收费标识
    private static boolean beWantOnFee = false;
    //入口车型
    public int enVehicleType = 0;
    //入口轴数
    public int enAxleCount = 0;
    //入口HEX
    public String enStationHex = "";
    //出口车型
    public int exVehicleType = 0;
    //出口轴数
    public int exAxleCount = 0;
    //出口计费车型
    public int exFeeVehicleType = 0;
    //出口计费轴数
    public int exFeeAxleCount = 0;
    //出口车种
    public int exVehicleClass = 0;
    //入口车牌(含颜色)/
    public String enVehicleId = "";
    //出口识别车牌(含颜色)
    public String exVehicleId = "";

    @Autowired
    private MinFeeManager minFeeManager;

    @Autowired
    private GantryCalcUtils gantryCalcUtils;

    @Autowired
    private RosterUtils rosterUtils;

    @Autowired
    private Db3FileUtils db3FileUtils;

    /**
     * CPC开始计费
     *
     * @param request
     * @param response
     * @return
     * @throws CustomizeException
     */
    public FeeExCalcResponse run(FeeExCalcRequest request, FeeExCalcResponse response) throws CustomizeException {
        // 1、分析obu文件信息内容,解析到实体里
        request.parseTagFiles();
        // 2、对入出口时间、车牌、车型、轴数、车种、发行方等先批量处理
        this.init(request);
        // 3、兜底计费
        long s1 = System.currentTimeMillis();
        response = this.getMinFee(request, response);
        long s2 = System.currentTimeMillis();
        logger.info("最小费额算费结束,耗时{}毫秒", s2 - s1);
        // 4、标签卡内计费
        response = this.tagFee(request, response);
        long s3 = System.currentTimeMillis();
        logger.info("卡内计费交易算费结束,耗时{}毫秒", s3 - s2);

        if (beWantOnFee) {
            logger.info("CPC计费超出阙值,走在线交易计费");
            // 5、在线计费
            response = this.specialFee(request, response);
        }
        if (response.getCode() != 0) {
            response.setMiniFeeInfo(null);
            response.setCpcFeeInfo(null);
        }
        return response;
    }

    /**
     * 批量处理基本数据，设置异常特情
     *
     * @param request
     */
    public void init(FeeExCalcRequest request) {
        enStationHex = request.getEnStationHex();
        enTime = DateUtils.dateTime(DateUtils.YYYY_MM_DD_TT_HH_MM_SS, request.getEnTime());
        exTime = DateUtils.dateTime(DateUtils.YYYY_MM_DD_TT_HH_MM_SS, request.getExTime());
        enVehicleId = BasicUtil.formatVehicleId(request.cpcEf01Model.getPlateNumber());
        exVehicleId = BasicUtil.formatVehicleId(request.getVehicleId());
        // 入出口车型、轴数
        enVehicleType = request.getEnVehicleType();
        enAxleCount = request.getEnAxleCount();
        exVehicleType = request.getExVehicleType();
        exAxleCount = request.getExAxleCount();
        //入出口车种处理
//        enVehicleClass = request.cpcEf01Model.chkEnVClass();
        exVehicleClass = request.getVehicleClass();

        //重置特情类型
        BasicUtil.resetSpecialInfo();
        //入出口车型对比
        if (enVehicleType != exVehicleType) {
            BasicUtil.setSpecialInfo(SpecialSituation.TYPE51.getValue());
            logger.warn(SpecialSituation.TYPE51.getDescription());
        }
        //入出口车牌对比
        if (!BasicUtil.compareVehicleId(enVehicleId, exVehicleId, false)) {
            BasicUtil.setSpecialInfo(SpecialSituation.TYPE52.getValue());
            logger.warn(SpecialSituation.TYPE52.getDescription());
        }
        //入出口轴数对比
//        if (enAxleCount != exAxleCount) {
//            BasicUtil.setSpecialInfo(SpecialSituation.TYPE60.getValue());
//            logger.warn(SpecialSituation.TYPE60.getDescription());
//        }
        //U型车检查
        if (Objects.equals(request.getEnStationHex(), request.getExStationHex())) {
            BasicUtil.setSpecialInfo(SpecialSituation.TYPE111.getValue());
            logger.warn(SpecialSituation.TYPE111.getDescription());
        }

        // 入出口计费车型、计费轴数处理
//        enFeeVehicleType = Vtype.feeVType(enVehicleClass, 0xff, enVehicleType, enAxleCount);
//        enFeeAxleCount = Vtype.feeAxles(enVehicleClass, 0xff, enVehicleType, enAxleCount);
        exFeeVehicleType = Vtype.feeVType(exVehicleClass, 0xff, exVehicleType, exAxleCount);
        exFeeAxleCount = Vtype.feeAxles(exVehicleClass, 0xff, exVehicleType, exAxleCount);
        lastGantryTime = request.cpcEf02Model.newGantryTime;

        logger.info("卡基本信息：卡内部编号：{}，发行方：{}，车牌号：{}，车型：{}，入口站号：{}，入口车道：{}，入口时间：{}，过省数量：{}", request.cpcMfEf01Model.cpcCardNo, request.cpcMfEf01Model.issuerCode, request.cpcEf01Model.getPlateNumber(), request.cpcEf01Model.vehicleType, request.cpcEf01Model.enStationId, request.cpcEf01Model.enLaneId, DateUtils.convertTimestamp(request.cpcEf01Model.enTime), request.cpcEf02Model.provCount);

        logger.info("请求参数信息：入出口站：[{}]-[{}]，入出口时间：[{}]-[{}]，入出口车牌：[{}]-[{}]，入出口车型：[{}]-[{}]，入出口轴数：[{}]-[{}]，车种：{}，用户类型：{}，状态标识：{}，passId：{}", request.getEnStationId(), request.getExStationId(), DateUtils.convertTime(request.getEnTime()), DateUtils.convertTime(request.getExTime()), request.cpcEf01Model.getPlateNumber(), request.getVehicleId(), request.getEnVehicleType(), request.getExVehicleType(), request.getEnAxleCount(), request.getExAxleCount(), exVehicleClass, request.getVehicleUserType(), request.getVehicleSign(), request.getPassId());
    }

    /**
     * 兜底计费,分省合并
     *
     * @param request
     * @param response
     * @return
     * @throws CustomizeException
     */
    public FeeExCalcResponse getMinFee(FeeExCalcRequest request, FeeExCalcResponse response) throws CustomizeException {
        // 获取最小费额版本号
        boolean bETC = false;
        try {
            MiniFeeInfo miniFeeInfo = new MiniFeeInfo();
            String minVersion = minFeeManager.getMinFeeVersion();
            miniFeeInfo.spcRateVersion = minVersion;

            ArrayList<SplitProvinceMini> minProvinces = new ArrayList<>();
            if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                //陕西
                try {
                    db3FileUtils.loadDb3File(request.getEnStationId(), request.getExStationId(), exVehicleType);
                    minProvinces = minFeeManager.getMinFee(bETC, request.getEnStationId(), request.getExStationId(), exVehicleType);
                } catch (Exception e) {
                    throw new CustomizeException("获取最小费额失败");
                }
            } else {
                minProvinces = rosterUtils.getMiniFee(request.getEnStationId(), request.getExStationId(), exVehicleType, exAxleCount, bETC);
            }
            if (minProvinces.isEmpty()) {
                throw new CustomizeException("获取兜底计费失败：查询不到对应的出口计费信息");
            }

            // 汇总最小费额信息
            for (SplitProvinceMini prov : minProvinces) {
                miniFeeInfo.zMinPayFee += prov.ziMinPayFee;
                miniFeeInfo.zMinFee += prov.ziMinFee;
                miniFeeInfo.calMinFeeFee += prov.calMinFeeFee;
                miniFeeInfo.calMinFeeFee95 += prov.calMinFeeFee95;
                miniFeeInfo.calMinFeeMileage += prov.calMinFeeMileage;
            }
            miniFeeInfo.splitProvince = minProvinces;
            //陕西合并分省信息
            if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                miniFeeInfo.merge();
            }

            response.setSpcRateVersion(minVersion);
            response.setMiniFeeInfo(miniFeeInfo);
            response.setExitFeeType(6);
            logger.info("最小费额结果：通行省份个数：{}，总应收：{}元，总实收：{}元，95折总实收：{}元，总里程：{}公里，费额费率版本号：{}", miniFeeInfo.splitProvince.size(), PayUtil.convertFee(miniFeeInfo.calMinFeeFee), PayUtil.convertFee(miniFeeInfo.zMinFee), PayUtil.convertFee(miniFeeInfo.calMinFeeFee95), PayUtil.convertMileage(miniFeeInfo.calMinFeeMileage), minVersion);

        } catch (CustomizeException e) {
            throw new CustomizeException(!e.getMessage().isEmpty() ? e.getMessage() : "获取兜底计费异常");
        }
        return response;
    }

    /**
     * 动态库计费，分省合并
     *
     * @param request
     * @param response
     * @return
     * @throws CustomizeException
     */
    public FeeExCalcResponse tagFee(FeeExCalcRequest request, FeeExCalcResponse response) throws CustomizeException {
        CpcFeeInfo cpcFeeInfo = new CpcFeeInfo();
        //调取动态库获取计费信息
        FeeEntryInfoModel cpcDto = JSONObject.parseObject(JSON.toJSONString(request), FeeEntryInfoModel.class);
        cpcDto.setTagType(2);
        cpcDto.setLaneStatus(2);
        cpcDto.setAxleCount(request.cpcEf01Model.axleCount);
        cpcDto.setCardType(request.getCPUCardType());
        cpcDto.setCardVer(request.getCPUVersion());
        cpcDto.setVehicleType(request.getExVehicleType());
        cpcDto.setEnAxleCount(enAxleCount);
        cpcDto.setVehicleClass(request.getVehicleClass());
        cpcDto.setPlateHex(request.getVehicleId().split("_")[0]);
        cpcDto.setPlateColor(Integer.valueOf(request.getVehicleId().split("_")[1]));
        cpcDto.setIssuerId("0");
        if (StringUtils.isNotEmpty(request.getVehicleSign())) {
            String hex = request.getVehicleSign();
            if (hex.startsWith("0x") || hex.startsWith("0X")) {
                hex = hex.substring(2);
            }
            cpcDto.setVehicleStatusFlag(Integer.parseInt(hex, 16));
        } else {
            cpcDto.setVehicleStatusFlag(0xFF);
        }
        cpcDto.setVehicleWeightLimits(0);
        cpcDto.setTotalWeight(new BigDecimal(request.cpcEf01Model.totalWeight).intValue());
        cpcDto.setEnTollStationHex(enStationHex);
        cpcDto.setEnPassTime(request.getEnTime());
        cpcDto.setLastGantryHex(request.cpcEf02Model.newGantryNo);
        cpcDto.setLastPassTime(LocalDateTime.parse(DateEx.ut2str(new BigDecimal(lastGantryTime).intValue(), "yyyy-MM-dd'T'HH:mm:ss")));
        cpcDto.setCurPassTime(request.cpcEf02Model.lastGantryTime("yyyy-MM-dd'T'HH:mm:ss"));
        cpcDto.setFeeProvBeginHex(request.cpcEf02Model.provEntryHex);
        cpcDto.setFeeProvMileage(request.cpcEf02Model.sumMileage);
        cpcDto.setPayFeeSumLocal(request.cpcEf02Model.provSumPayFee);
        cpcDto.setGantryPassNum(request.cpcEf02Model.gantryNum);
        cpcDto.setGantryPassHex(request.cpcEf02Model.gantryPass());
        cpcDto.setFeeProvGantryNum(request.cpcEf02Model.gantryCount);
        cpcDto.setRealFeeSumLocal(-1);
        cpcDto.setFeeSumLocal(0);
        EntryFeeCalcResponse responseDto = gantryCalcUtils.libraryFee(cpcDto);
        if (responseDto.getCode() != 0) {
            response.setCode(-1);
            response.setCodeInfo(responseDto.getMsg());
            response.setMiniFeeInfo(null);
            response.setRateVersion(null);
            response.setSpcRateVersion(null);
            throw new CustomizeException(responseDto.getMsg());
        } else {
            response.setRateVersion(responseDto.getParamVersion());
            // 多省判断
            if (request.cpcEf02Model.provCount > 1 || !request.cpcEf01Model.tstLocalEntry(request.getExStationHex())) {
                cpcFeeInfo.zMultiProvinces = true;
                cpcFeeInfo.zProvinceCount = request.cpcEf02Model.provCount;
            } else {
                cpcFeeInfo.zMultiProvinces = false;
                cpcFeeInfo.zProvinceCount = 1;
            }

            // 汇总前序行程收费信息(不含最后行程信息)
            cpcFeeInfo.setPrevTrip(request.cpcEf02Model.provCount, request.cpcEf04Model, enStationHex);
            // 添加最后行程并设置计费信息
            int provinceId = 0;
            if (request.getExStationHex().startsWith(Issuer.Issue140101.getProvinceCode())) {
                provinceId = 14;
            } else if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                provinceId = 61;
            }
            // 添加最后一段本省行程
            cpcFeeInfo.addLastTrip(responseDto, exTime, provinceId, request.cpcEf04Model, request.cpcEf02Model.provCount, enStationHex);
            //陕西合并分省信息
            if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                cpcFeeInfo.merge();
            }
            logger.info("CPC计费结果：通行省份个数：{}，总应收：{}元，总优惠：{}元，总实收：{}元，总里程：{}公里", cpcFeeInfo.splitProvince.size(), PayUtil.convertFee(cpcFeeInfo.payFee), PayUtil.convertFee(cpcFeeInfo.discountFee), PayUtil.convertFee(cpcFeeInfo.fee), PayUtil.convertMileage(cpcFeeInfo.feeMileage));
        }

        // 标签计费正常阈值校验
        int cardFee = 0;
        int minFee = 0;
        int cardFeeMileage = 0;
        int minMileage = 0;
        //总应收
        cardFee = cpcFeeInfo.fee;
        //最小费额里程
        minMileage = response.miniFeeInfo.calMinFeeMileage;
        //最小费额应收
        minFee = response.miniFeeInfo.calMinFeeFee;
        //总里程
        cardFeeMileage = cpcFeeInfo.feeMileage;
        if (request.getValidShortFee() == null || request.getValidShortFee() == 1) {
            if (request.getExStationHex().startsWith(Issuer.Issue140101.getProvinceCode())) {
                if (exVehicleType < 10 || exAxleCount <= 6) {
                    //客车与6轴以下货车
//                        if (cardFee == 0) {
//                            cardFee = 1;
//                        }
//
//                        // 获取MTC兜底收费金额
//                        // 需要对本省免费进行强制免费处理
//                        if (minFee == 0) {
//                            minFee = 1;
//                        }
                    /**
                     *
                     * a)最小费额应收下限值：最小费额应收金额
                     * b)最小费额应收上限值：最小费额应收金额*1.5
                     * c)最小费额应收里程上限值：最小费额应收里程*1.5
                     * d)设备内应收金额大于等于最小费额应收下限值且
                     * 设备内应收金额小于等于最小费额应收上限值时使用设备内金额计费
                     * e)设备内应收金额大于等于最小费额应收下限值且
                     * 设备内应收金额大于最小费额应收上限值且
                     * 设备内里程小于最小费额应收里程上限值时使用设备内金额计费
                     * f)不满足以上条件则转在线计费
                     */
                    if (cardFee >= minFee && cardFee <= minFee * 1.5f) {
                        beWantOnFee = false;
                    } else {
                        beWantOnFee = cardFee < minFee || !(cardFee > minFee * 1.5f) || !(cardFeeMileage < minMileage * 1.5f);
                    }
                } else {
                    //6轴以上货车
                    //外省兜底应收金额
                    int otherProMinFee = response.miniFeeInfo.payFeeProvSumOther();
                    //本省兜底应收金额
                    double selfProMinFee = response.miniFeeInfo.payFeeProvSumLocal();
                    double selfProMinFee1 = selfProMinFee * (1 + (exAxleCount - 6) * 0.2f);
                    //通行省份个数
                    int proNum = request.cpcEf02Model.provCount;
                    double folowFee = (otherProMinFee + selfProMinFee1) - proNum * 50f;
                    beWantOnFee = !(cardFee >= folowFee);
                }
            }
        } else {
            //包年车辆：15-绕城包年 16-西阎包年 17-绕城西阎包年
            int vehicleUserType = request.getVehicleUserType();
            int basicAmount = 0;
            double amount = 0;
            double lowAmount;
            double upperAmount = minFee * 5f;
            if (vehicleUserType == 15) {
                basicAmount = 4371;
                amount = minFee * 0.9f - basicAmount;
                lowAmount = amount < 0 ? 0 : amount;
            } else if (vehicleUserType == 16) {
                basicAmount = 2825;
                amount = minFee * 0.9f - basicAmount;
                lowAmount = amount < 0 ? 0 : amount;
            } else if (vehicleUserType == 17) {
                basicAmount = 7196;
                amount = minFee * 0.9f - basicAmount;
                lowAmount = amount < 0 ? 0 : amount;
            } else {
                lowAmount = minFee * 0.9f;
            }

            beWantOnFee = !(cardFee >= lowAmount) || !(cardFee <= upperAmount);
        }

        if (!beWantOnFee) {
            response.setCpcFeeInfo(cpcFeeInfo);
            response.setExitFeeType(3);
        }
        return response;
    }

    /**
     * 特情计费,合并分省
     *
     * @param request
     * @param response
     * @return
     * @throws CustomizeException
     */
    public FeeExCalcResponse specialFee(FeeExCalcRequest request, FeeExCalcResponse response) throws CustomizeException {
        OnlineFeeInfo onlineFeeInfo = new OnlineFeeInfo();
        CustomOnlineResponse spececReponse = new CustomOnlineResponse();
        long s1 = System.currentTimeMillis();
        if (request.getExStationHex().startsWith(Issuer.Issue140101.getProvinceCode())) {
            JinOnLineRequest onLineRes = new JinOnLineRequest();
            onLineRes.setMediaId(request.getMediaNo());
            onLineRes.setExStationId(request.getExStationHex() + "|" + request.getExStationId());
            onLineRes.setExTime(request.getExTime());
            onLineRes.setVehicleId(request.getVehicleId());
            onLineRes.setVehicleType(request.getExVehicleType());
            onLineRes.setVehicleClass(request.getVehicleClass());
            if (request.getPayType() != null) {
                onLineRes.setPayType(request.getPayType());
            }
            onLineRes.setPassId(request.getPassId());
            onLineRes.setEnStationId(request.getEnStationHex() + "|" + request.getEnStationId());
            onLineRes.setFeeType(1);
            onLineRes.setAxleCount(request.getExAxleCount());
            onLineRes.setEnTime(request.getEnTime());
            onLineRes.setSecondConfirm(1);
            onLineRes.setIsETC(request.getIsDiscount());
            onLineRes.setMediaType(request.getMediaType());
            onLineRes.setEnTollLaneId(request.getEnTollLaneId());
            onLineRes.setExTollLaneId(request.getExTollLaneId());
            onLineRes.setIsMultiProv(1);
            onLineRes.setVehicleUserType(request.getVehicleUserType());
            onLineRes.setIssuerId(request.getIssuerId());
            onLineRes.setReqVersion(Long.parseLong(DateUtils.dateTime()));
            onLineRes.setVehicleSign(request.getVehicleSign());
            spececReponse = rosterUtils.getJinExOnlineFee(onLineRes, response);
        } else {
            QinOnLineRequest onLineRes = new QinOnLineRequest();
            onLineRes.setRequestId(IdUtils.fastSimpleUUID());
//            onLineRes.setSplitProvince(IdUtils.fastSimpleUUID());
            onLineRes.setRequestType(11);
            onLineRes.setMultiProvince(request.cpcEf02Model.provCount > 1 ? 1 : 0);
            onLineRes.setPassId(request.getPassId());
            if (onLineRes.getMultiProvince() == 0) {
                onLineRes.setGantryCount(request.cpcEf02Model.gantryCount);
                onLineRes.setGantryProvFee(request.cpcEf02Model.provSumPayFee);
                onLineRes.setGantryHexGroup(request.cpcEf02Model.gantryPass());
            }
            onLineRes.setMediaType(request.getMediaType());
            onLineRes.setMediaNo(request.getMediaNo());
            onLineRes.setIssuerId(request.getIssuerId());
//            onLineRes.setIssuerId(request.card0015Model.getIssuerId6());
            onLineRes.setIsDiscount(request.getIsDiscount());
            onLineRes.setValidShortFee(request.getValidShortFee() == null || request.getValidShortFee() == 1 ? 1 : 2);
            onLineRes.setEnLaneId(request.getEnTollLaneId());
            onLineRes.setEnTime(request.getEnTime());
            onLineRes.setVehicleId(request.getVehicleId());
            onLineRes.setExLaneId(request.getExTollLaneId());
            onLineRes.setExTime(request.getExTime());
            onLineRes.setVehicleType(request.getExVehicleType());
            onLineRes.setVehicleUserType(request.getVehicleUserType());
            onLineRes.setAxleCount(request.getExAxleCount());
            spececReponse = rosterUtils.getQinExOnlineFee(onLineRes, response);
        }
        long s2 = System.currentTimeMillis();
        logger.info("在线计费交易算费结束,耗时{}毫秒", s2 - s1);
        if (spececReponse.getOnlineSpececResponse().getCalculateResult() == 1) {
            onlineFeeInfo.setSplitProDetail(spececReponse.getOnlineSpececResponse());
            //陕西合并分省信息
            if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                onlineFeeInfo.merge();
            }
            logger.info("在线计费结果：通行省份个数：{}, 总应收：{}元, 总实收：{}元, 总优惠：{}元, 总拆分：{}元, 总里程：{}公里", onlineFeeInfo.splitProvince.size(), PayUtil.convertFee(onlineFeeInfo.payFee), PayUtil.convertFee(onlineFeeInfo.fee), PayUtil.convertFee(onlineFeeInfo.discountFee), PayUtil.convertFee(onlineFeeInfo.splitAmount), PayUtil.convertMileage(onlineFeeInfo.feeMileage));
        } else {
            beWantMinFee = true;
            logger.info("在线计费失败,走兜底计费");
            return response;
        }

        // 比较阙值
        int spFee = 0;
        int minFee = 0;
        int spMileage = 0;
        int minMileage = 0;
        //在线计费应收金额
        spFee = onlineFeeInfo.getPayFee();
        //最小费额应收金额
        minFee = response.miniFeeInfo.calMinFeeFee;
        //在线计费总里程
        spMileage = onlineFeeInfo.getFeeMileage();
        //最小费额里程
        minMileage = response.miniFeeInfo.calMinFeeMileage;
        //是否验证最小费额，请求参数里里带入
        if (request.getValidShortFee() == null || request.getValidShortFee() == 1) {
            if (request.getExStationHex().startsWith(Issuer.Issue140101.getProvinceCode())) {
                //根据山西计费规则。分为客车与6轴以下货车和6轴以上货车
                if (request.getExVehicleType() < 10 || request.getExAxleCount() <= 6) {
                    if (spFee >= minFee * 0.9f && spFee <= minFee * 1.5f) {
                        // d)在线计费应收金额大于等于最小费额应收下限值且
                        // 在线计费应收金额小于等于最小费额应收上限值时使用在线计费金额计费
                        beWantOnFee = true;
                    } else if (spFee > minFee * 1.5f && spMileage < minMileage * 1.5f) {
                        //e)在线计费应收金额大于最小费额应收上限值且
                        //在线计费里程小于最小费额应收里程上限值时使用在线计费金额计费
                        beWantOnFee = true;
                    } else if (spFee > minFee * 1.5f && spMileage > minMileage * 1.5f) {
                        //f)在线计费应收金额大于最小费额应收上限值且
                        //在线计费里程大于最小费额应收里程上限值时需要监控授权是否使用在线计费金额，如果监控回控同意则使用
                        logger.info("监控授权...");
//                    beWantMinFee = false;
                    } else {
                        //g)不满足以上条件则转最小费额计费
                        beWantMinFee = true;
                        beWantOnFee = false;
                    }
                } else {
                    //6轴以上货车
                    //外省兜底应收金额
                    int otherProMinFee = response.miniFeeInfo.payFeeProvSumOther();
                    //本省兜底应收金额
                    double selfProMinFee = response.miniFeeInfo.payFeeProvSumLocal();
                    double selfProMinFee1 = selfProMinFee * (1 + (exAxleCount - 6) * 0.2f);
                    //通行省份个数
                    int proNum = request.cpcEf02Model.provCount;
                    double folowFee = (otherProMinFee + selfProMinFee1) - proNum * 50f;
                    if (spFee >= folowFee) {
                        beWantOnFee = true;
                    } else {
                        beWantMinFee = true;
                    }
                }
            } else {
                //包年车辆：15-绕城包年 16-西阎包年 17-绕城西阎包年
                int vehicleUserType = request.getVehicleUserType();
                int basicAmount = 0;
                double amount = 0;
                double lowAmount;
                double upperAmount = minFee * 5f;
                if (vehicleUserType == 15) {
                    basicAmount = 4371;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else if (vehicleUserType == 16) {
                    basicAmount = 2825;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else if (vehicleUserType == 17) {
                    basicAmount = 7196;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else {
                    lowAmount = minFee * 0.9f;
                }

                beWantMinFee = !(spFee >= lowAmount) || !(spFee <= upperAmount);
            }
        }

        if (!beWantMinFee) {
            response.setOnlineFeeInfo(onlineFeeInfo);
            response.setMiniFeeInfo(null);
        } else {
            response.setExitFeeType(6);
        }
        return response;
    }
}
